<template>
  <div class="projects-container">
    <div class="main-card">
      <!-- 页面标题 -->
      <div class="card-header">
        <h2 class="card-title">项目管理</h2>
      </div>
      
      <div class="search-section">
        <div class="search-container">
          <div class="search-item">
            <span class="search-label">关键词</span>
            <el-input v-model="queryParams.keyword" placeholder="请输入关键词" clearable @keyup.enter="handleQuery"
              class="search-input">
              <template #prefix>
                <el-icon>
                  <Search />
                </el-icon>
              </template>
            </el-input>
          </div>
          <div class="search-item">
            <span class="search-label">项目分类</span>
            <el-select v-model="queryParams.projectCategoryId" placeholder="请选择分类" clearable 
              class="search-input">
              <el-option v-for="item in categoryOptions" :key="item.id" :label="item.name" :value="item.id" />
            </el-select>
          </div>
          <div class="search-item">
            <span class="search-label">技术栈</span>
            <el-input v-model="queryParams.techStack" placeholder="多个技术栈英文逗号隔开" clearable @keyup.enter="handleQuery"
              class="search-input">
            </el-input>
          </div>
          <div class="search-item">
            <span class="search-label">状态</span>
            <el-select v-model="queryParams.status" placeholder="请选择状态" clearable 
              class="search-input">
              <el-option :label="'上架'" :value="1" />
              <el-option :label="'下架'" :value="0" />
            </el-select>
          </div>
          <div class="search-buttons">
            <el-button type="primary" @click="handleQuery" :icon="Search">查询</el-button>
            <el-button @click="resetQuery" :icon="RefreshRight">重置</el-button>
          </div>
        </div>
      </div>

      <!-- 工具栏 -->
      <div class="table-toolbar">
        <el-button type="primary" @click="handleAdd" :icon="Plus">新增项目</el-button>
      </div>

      <!-- 表格区域 -->
      <div class="table-section">
        <el-table :data="tableData" fit v-loading="loading" border stripe highlight-current-row
          :cell-style="{ textAlign: 'center' }">
          <el-table-column prop="id" label="ID" align="center" width="80" />
          <el-table-column label="项目封面" align="center" width="100">
            <template #default="{ row }">
              <el-image 
                :src="row.cover" 
                fit="cover"
                style="width: 60px; height: 60px; border-radius: 4px;"
                :preview-src-list="[row.cover]">
                <template #error>
                  <div class="image-placeholder">
                    <el-icon><Picture /></el-icon>
                  </div>
                </template>
              </el-image>
            </template>
          </el-table-column>
          <el-table-column prop="name" label="项目名称" align="center" />
          <el-table-column label="所属分类" align="center">
            <template #default="{ row }">
              <el-tag
                :type="getRandomTagType(row.projectCategoryId)"
                :effect="getRandomEffect(row.projectCategoryId)"
                class="tag-item"
              >
                {{ getCategoryName(row.projectCategoryId) }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column prop="price" label="价格" align="center">
            <template #default="{ row }">
              <span>￥{{ row.price }}</span>
            </template>
          </el-table-column>
          <el-table-column label="技术栈" align="center">
            <template #default="{ row }">
              <div class="tech-stack-tags">
                <el-tag 
                  v-for="(item, index) in row.techStack?.split(',')" 
                  :key="index"
                  size="small"
                  :type="getRandomTagType(index)"
                  class="tag-item"
                >
                  {{ item.trim() }}
                </el-tag>
              </div>
            </template>
          </el-table-column>
          <el-table-column prop="description" label="描述" align="center" min-width="180">
            <template #default="{ row }">
              <div class="description-cell">
                <el-popover
                  placement="top"
                  :width="400"
                  trigger="hover"
                  v-if="row.description"
                >
                  <template #reference>
                    <el-tag
                      type="info"
                      effect="plain"
                      class="description-tag"
                    >
                      {{ truncateText(row.description, 50) }}
                    </el-tag>
                  </template>
                  <div class="description-popover">
                    <div class="description-title">项目描述</div>
                    <div class="description-content">{{ row.description }}</div>
                  </div>
                </el-popover>
                <span v-else class="no-description">暂无描述</span>
              </div>
            </template>
          </el-table-column>
          <el-table-column prop="viewCount" label="浏览量" align="center" />
          <el-table-column label="状态" align="center" width="100">
            <template #default="{ row }">
              <el-tag :type="row.status === 1 ? 'success' : 'info'">
                {{ row.status === 1 ? '上架' : '下架' }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column prop="createTime" label="创建时间" align="center" width="160" />
          <el-table-column label="操作" align="center" fixed="right" width="180">
            <template #default="{ row }">
              <el-button type="primary" link @click="handleEdit(row)" class="action-button">
                <el-icon><Edit /></el-icon>
                <span>编辑</span>
              </el-button>
              <el-button type="success" link @click="handleView(row)" class="action-button">
                <el-icon><View /></el-icon>
                <span>查看</span>
              </el-button>
              <el-button type="danger" link @click="handleDelete(row)" class="action-button">
                <el-icon><Delete /></el-icon>
                <span>删除</span>
              </el-button>
            </template>
          </el-table-column>
        </el-table>

        <!-- 分页区域 -->
        <div class="pagination-container">
          <el-pagination v-model:current-page="queryParams.pageNum" v-model:page-size="queryParams.pageSize"
            :page-sizes="[10, 20, 50, 100]" background layout="total, sizes, prev, pager, next, jumper" :total="total"
            @size-change="handleSizeChange" @current-change="handleCurrentChange" />
        </div>
      </div>
    </div>

    <!-- 项目编辑对话框 -->
    <el-dialog v-model="dialogVisible" :title="dialogTitle" width="600px" destroy-on-close>
      <el-form v-if="formData" :model="formData" label-width="100px" :rules="rules" ref="formRef">
        <el-form-item label="项目名称" prop="name" required>
          <el-input v-model="formData.name" placeholder="请输入项目名称" />
        </el-form-item>
        <el-form-item label="所属分类" prop="projectCategoryId" required>
          <el-select v-model="formData.projectCategoryId" placeholder="请选择分类" class="form-select">
            <el-option v-for="item in categoryOptions" :key="item.id" :label="item.name" :value="item.id" />
          </el-select>
        </el-form-item>
        <el-form-item label="项目封面" prop="cover" required>
          <div class="upload-container">
            <div v-if="formData.cover" class="preview-container">
              <el-image :src="formData.cover" style="width: 100px; height: 100px; object-fit: cover;" />
              <div class="preview-actions">
                <el-button type="primary" link @click="formData.cover = ''">
                  <el-icon><Delete /></el-icon>
                  <span>删除</span>
                </el-button>
              </div>
            </div>
            <div v-else>
              <FileUploader
                ref="coverFileRef"
                buttonText="上传封面"
                accept="image/*"
                :code="2"
                @upload-success="handleCoverUploadSuccess"
              />
              <div class="upload-tip">建议尺寸: 400x400px, 格式: JPG/PNG</div>
            </div>
          </div>
        </el-form-item>
        <el-form-item label="项目价格" prop="price" required>
          <div class="price-input-container">
            <el-input v-model="formData.price" placeholder="请输入价格" @input="handlePriceInput" class="price-input">
              <template #prefix>￥</template>
            </el-input>
            <el-button type="primary" @click="incrementPrice">+1</el-button>
          </div>
          <div class="upload-tip">输入数字，支持小数点后两位</div>
        </el-form-item>
        <el-form-item label="下载密码" prop="password" required>
          <el-input v-model="formData.password" placeholder="请输入下载密码" show-password />
          <div class="form-tip">用户下载文件时需要输入的密码</div>
        </el-form-item>
        <el-form-item label="技术栈" prop="techStack" required>
          <el-input v-model="formData.techStack" placeholder="多个技术栈英文逗号隔开" />
          <div class="form-tip">多个技术栈请用英文逗号分隔</div>
        </el-form-item>
        <el-form-item label="项目视频" prop="videoUrl" required>
          <div class="upload-container">
            <div v-if="formData.videoUrl" class="preview-container">
              <div class="video-preview">
                <el-icon><VideoPlay /></el-icon>
                <span>{{ formData.videoUrl.substring(formData.videoUrl.lastIndexOf('/') + 1) }}</span>
              </div>
              <div class="preview-actions">
                <el-button type="primary" link @click="formData.videoUrl = ''">
                  <el-icon><Delete /></el-icon>
                  <span>删除</span>
                </el-button>
              </div>
            </div>
            <div v-else>
              <FileUploader
                ref="videoFileRef"
                buttonText="上传视频"
                accept="video/*"
                :code="3"
                @upload-success="handleVideoUploadSuccess"
              />
              <div class="upload-tip">支持格式: MP4/AVI/MOV，大文件上传可能需要较长时间</div>
            </div>
          </div>
        </el-form-item>
        <el-form-item label="项目文件" prop="fileName" required>
          <div class="upload-container">
            <div v-if="formData.fileName" class="preview-container">
              <div class="file-preview">
                <el-icon><Document /></el-icon>
                <span>{{ formData.fileName }}</span>
              </div>
              <div class="preview-actions">
                <el-button type="primary" link @click="formData.fileName = ''">
                  <el-icon><Delete /></el-icon>
                  <span>删除</span>
                </el-button>
              </div>
            </div>
            <div v-else>
              <FileUploader
                ref="projectFileRef"
                buttonText="上传文件"
                accept=".zip,.rar,.7z,.tar,.gz"
                :code="2"
                @upload-success="handleProjectFileUploadSuccess"
              />
              <div class="upload-tip">支持常见压缩文件格式</div>
            </div>
          </div>
        </el-form-item>
        <el-form-item label="项目描述" prop="description" required>
          <el-input v-model="formData.description" type="textarea" :rows="3" placeholder="请输入项目描述" />
        </el-form-item>
        <el-form-item label="项目状态" prop="status" required>
          <el-radio-group v-model="formData.status">
            <el-radio :label="1">上架</el-radio>
            <el-radio :label="0">下架</el-radio>
          </el-radio-group>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="dialogVisible = false">取消</el-button>
          <el-button type="primary" @click="submitForm" :loading="submitLoading">提交</el-button>
        </div>
      </template>
    </el-dialog>

    <!-- 密码输入对话框 -->
    <el-dialog v-model="passwordVisible" title="请输入下载密码" width="400px">
      <el-form @submit.prevent="confirmDownload">
        <el-form-item label="密码" required>
          <el-input v-model="downloadPassword" placeholder="请输入密码" type="password" show-password @keyup.enter="confirmDownload" />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="passwordVisible = false">取消</el-button>
          <el-button type="primary" @click="confirmDownload" :loading="downloadLoading">确认下载</el-button>
        </div>
      </template>
    </el-dialog>

    <!-- 项目资源查看对话框 -->
    <el-dialog v-model="viewDialogVisible" :title="`查看项目：${currentProject?.name || ''}`" width="700px">
      <div class="project-resources" v-if="currentProject">
        <div class="resources-list">
          <!-- 项目封面 -->
          <div class="resource-card" v-if="currentProject.cover">
            <div class="resource-card-header">
              <div class="resource-title">
                <el-icon><Picture /></el-icon>
                <span>项目封面</span>
              </div>
              <el-button type="primary" link @click="handleViewImage(currentProject)">
                <el-icon><View /></el-icon>
                <span>查看大图</span>
              </el-button>
            </div>
            <div class="resource-card-body">
              <el-image 
                :src="currentProject.cover" 
                fit="cover" 
                class="cover-image" 
                :preview-src-list="[currentProject.cover]"
              >
                <template #error>
                  <div class="image-placeholder">
                    <el-icon><Picture /></el-icon>
                    <span>加载失败</span>
                  </div>
                </template>
              </el-image>
            </div>
          </div>

          <!-- 项目视频 -->
          <div class="resource-card" v-if="currentProject.videoUrl">
            <div class="resource-card-header">
              <div class="resource-title">
                <el-icon><VideoPlay /></el-icon>
                <span>项目视频</span>
              </div>
              <el-button type="primary" link @click="toggleVideoPlay">
                <el-icon>
                  <VideoPlay v-if="!isVideoPlaying" />
                  <VideoPause v-else />
                </el-icon>
                <span>{{ isVideoPlaying ? '关闭播放' : '播放视频' }}</span>
              </el-button>
            </div>
            <div class="resource-card-body">
              <div v-if="isVideoPlaying" class="video-player-container">
                <video 
                  :src="currentProject.videoUrl" 
                  controls 
                  autoplay 
                  class="video-player" 
                  ref="videoPlayer"
                  @ended="isVideoPlaying = false"
                ></video>
              </div>
              <div v-else class="video-thumbnail" @click="toggleVideoPlay">
                <el-icon class="play-icon"><VideoPlay /></el-icon>
                <span>点击播放视频</span>
              </div>
            </div>
          </div>

          <!-- 项目文件 -->
          <div class="resource-card" v-if="currentProject.fileName">
            <div class="resource-card-header">
              <div class="resource-title">
                <el-icon><Document /></el-icon>
                <span>项目文件</span>
              </div>
              <el-button type="primary" link @click="handleViewFile(currentProject)">
                <el-icon><Download /></el-icon>
                <span>下载文件</span>
              </el-button>
            </div>
            <div class="resource-card-body file-body">
              <div class="file-info">
                <div class="file-icon">
                  <el-icon><Document /></el-icon>
                </div>
                <div class="file-details">
                  <div class="file-name">{{ currentProject.fileName }}</div>
                  <div class="file-type">{{ getFileType(currentProject.fileName) }}</div>
                </div>
              </div>
            </div>
          </div>
          
          <!-- 如果没有任何资源 -->
          <div class="no-resources" v-if="!currentProject.cover && !currentProject.videoUrl && !currentProject.fileName">
            <el-empty description="该项目没有可查看的资源" />
          </div>
        </div>
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="viewDialogVisible = false">关闭</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted, watch } from 'vue'
import { debounce } from 'lodash-es'
import axios from 'axios'
import { Search, RefreshRight, Edit, Delete, Plus, Picture, Upload, VideoPlay, Document, View, Download, VideoPause } from '@element-plus/icons-vue'
import { getProjectPageList, getProjectById, saveProject, deleteProjectById } from '@/api/project'
import { getProjectCategoryPageList } from '@/api/projectCategory'
import { uploadFile, downloadFile } from '@/api/file'
import FileUploader from '@/components/FileUploader.vue'

// 查询参数
const queryParams = reactive({
  keyword: '',
  projectCategoryId: undefined,
  techStack: undefined,
  status: undefined,
  type: 2,
  pageNum: 1,
  pageSize: 10
})

// 数据列表
const tableData = ref([])
const total = ref(0)
const loading = ref(false)
const categoryOptions = ref([])

// 编辑相关
const dialogVisible = ref(false)
const dialogTitle = ref('新增项目')
const formData = ref(null)
const formRef = ref(null)
const submitLoading = ref(false)

// 标签类型和效果
const tagTypes = ['primary', 'success', 'warning', 'danger', 'info']
const tagEffects = ['light', 'dark', 'plain']

// 根据ID获取随机但固定的标签类型
const getRandomTagType = (id) => {
  return tagTypes[id % tagTypes.length]
}

// 根据ID获取随机但固定的标签效果
const getRandomEffect = (id) => {
  return tagEffects[id % tagEffects.length]
}

// 获取分类名称
const getCategoryName = (categoryId) => {
  const category = categoryOptions.value.find(item => item.id === categoryId)
  return category ? category.name : '未知分类'
}

// 表单验证规则
const rules = {
  name: [
    { required: true, message: '请输入项目名称', trigger: 'blur' },
    { min: 1, max: 50, message: '长度在 1 到 50 个字符', trigger: 'blur' }
  ],
  projectCategoryId: [
    { required: true, message: '请选择项目分类', trigger: 'change' }
  ],
  description: [
    { required: true, message: '请输入项目描述', trigger: 'blur' }
  ],
  price: [
    { required: true, message: '请输入项目价格', trigger: 'blur' },
    { type: 'number', message: '价格必须为数字', trigger: 'blur' }
  ],
  status: [
    { required: true, message: '请选择项目状态', trigger: 'change' }
  ],
  cover: [
    { required: true, message: '请上传项目封面', trigger: 'blur' }
  ],
  techStack: [
    { required: true, message: '请输入技术栈', trigger: 'blur' }
  ],
  videoUrl: [
    { required: true, message: '请上传项目视频', trigger: 'blur' }
  ],
  fileName: [
    { required: true, message: '请上传项目文件', trigger: 'blur' }
  ],
  password: [
    { required: true, message: '请设置下载密码', trigger: 'blur' }
  ]
}

// 文件上传相关
const coverFileRef = ref(null)
const videoFileRef = ref(null)
const projectFileRef = ref(null)
const coverUploading = ref(false)
const videoUploading = ref(false)
const projectFileUploading = ref(false)

// 上传项目封面成功回调
const handleCoverUploadSuccess = (data) => {
  formData.value.cover = data.fileUrl
}

// 上传项目视频成功回调
const handleVideoUploadSuccess = (data) => {
  formData.value.videoUrl = data.fileUrl
}

// 上传项目文件成功回调
const handleProjectFileUploadSuccess = (data) => {
  // 只保存文件名
  const url = data.fileUrl
  const fileName = url.substring(url.lastIndexOf('/') + 1)
  formData.value.fileName = fileName
}

// 文件下载相关
const passwordVisible = ref(false)
const downloadPassword = ref('')
const downloadLoading = ref(false)
const currentProject = ref(null)
const viewDialogVisible = ref(false)
const isVideoPlaying = ref(false)
const videoPlayer = ref(null)

// 获取文件类型
const getFileType = (fileName) => {
  if (!fileName) return '';
  const extension = fileName.split('.').pop().toLowerCase();
  const typeMap = {
    'pdf': 'PDF 文档',
    'doc': 'Word 文档',
    'docx': 'Word 文档',
    'xls': 'Excel 表格',
    'xlsx': 'Excel 表格',
    'ppt': 'PowerPoint 演示文稿',
    'pptx': 'PowerPoint 演示文稿',
    'zip': 'ZIP 压缩包',
    'rar': 'RAR 压缩包',
    'txt': '文本文档',
    'jpg': 'JPG 图片',
    'jpeg': 'JPEG 图片',
    'png': 'PNG 图片',
    'mp4': 'MP4 视频',
    'avi': 'AVI 视频',
    'mov': 'MOV 视频'
  };
  return typeMap[extension] || `${extension.toUpperCase()} 文件`;
}

// 切换视频播放状态
const toggleVideoPlay = () => {
  isVideoPlaying.value = !isVideoPlaying.value;
  if (isVideoPlaying.value) {
    // 延迟执行以确保DOM已更新
    setTimeout(() => {
      if (videoPlayer.value) {
        videoPlayer.value.play();
      }
    }, 100);
  }
}

// 打开查看对话框
const handleView = (row) => {
  currentProject.value = row;
  viewDialogVisible.value = true;
  isVideoPlaying.value = false;
}

// 查看或下载文件
const handleViewFile = (row) => {
  if (row.fileName) {
    currentProject.value = row
    passwordVisible.value = true
    downloadPassword.value = ''
  } else {
    ElMessage.warning('该项目没有可下载的文件')
  }
}

// 查看图片
const handleViewImage = (row) => {
  if (row.cover) {
    window.open(row.cover, '_blank')
  } else {
    ElMessage.warning('该项目没有封面图片')
  }
}

// 下载文件
const confirmDownload = async () => {
  if (!currentProject.value || !currentProject.value.fileName) {
    ElMessage.warning('没有可下载的文件')
    return
  }
  
  downloadLoading.value = true
  try {
    const res = await downloadFile(2, currentProject.value.fileName, downloadPassword.value)
    
    // 检查响应类型是否为JSON
    if (res.type === 'application/json') {
      // 读取JSON内容
      const reader = new FileReader()
      reader.onload = function() {
        try {
          const jsonData = JSON.parse(reader.result)
          // 处理错误消息
          if (jsonData.code !== 200) {
            ElMessage.error(jsonData.msg || '下载失败，请检查密码是否正确')
          } else {
            ElMessage.error('下载失败，请稍后重试')
          }
        } catch (e) {
          ElMessage.error('下载失败，请稍后重试')
        }
      }
      reader.readAsText(res)
      downloadLoading.value = false
      return
    }
    
    // 如果不是JSON，按照正常二进制文件处理
    const blob = new Blob([res])
    const url = window.URL.createObjectURL(blob)
    const link = document.createElement('a')
    link.href = url
    link.download = currentProject.value.fileName
    link.click()
    window.URL.revokeObjectURL(url)
    
    ElMessage.success('文件下载成功')
    passwordVisible.value = false
  } catch (error) {
    ElMessage.error('下载失败，请检查密码是否正确')
  } finally {
    downloadLoading.value = false
  }
}

// 手动修改价格
const handlePriceInput = (value) => {
  // 确保输入的是有效数字
  if (value === '' || isNaN(Number(value))) {
    formData.value.price = 0
  } else {
    formData.value.price = parseFloat(value)
  }
}

// 价格加1
const incrementPrice = () => {
  formData.value.price = parseFloat((formData.value.price + 1).toFixed(2))
}

// 防抖处理查询
const debouncedQuery = debounce(() => {
  getList()
}, 300)

// 获取分类列表
const getCategoryList = async () => {
  try {
    const res = await getProjectCategoryPageList({ pageSize: 100 })
    if (res.code === 200) {
      categoryOptions.value = res.data.records
    }
  } catch (error) {
    console.error('获取分类列表出错:', error)
  }
}

// 获取项目列表
const getList = async () => {
  if (loading.value) return
  loading.value = true
  try {
    const params = {
      keyword: queryParams.keyword,
      projectCategoryId: queryParams.projectCategoryId,
      techStack: queryParams.techStack,
      status: queryParams.status,
      type: queryParams.type,
      pageNum: queryParams.pageNum,
      pageSize: queryParams.pageSize
    }
    const res = await getProjectPageList(params)
    if (res.code === 200) {
      tableData.value = res.data.records
      total.value = res.data.total
    } else {
      ElMessage.error({
        message: res.msg || '获取项目列表失败',
        duration: 3000,
        showClose: true
      })
    }
  } catch (error) {
    console.error('获取项目列表出错:', error)
    if (!error.code || error.code !== 403) {
      ElMessage.error({
        message: '获取项目列表出错，请稍后重试',
        duration: 3000,
        showClose: true
      })
    }
  } finally {
    loading.value = false
  }
}

// 查询按钮
const handleQuery = () => {
  queryParams.pageNum = 1
  debouncedQuery()
}

// 重置按钮
const resetQuery = () => {
  queryParams.keyword = ''
  queryParams.projectCategoryId = undefined
  queryParams.techStack = undefined
  queryParams.status = undefined
  queryParams.type = 2
  handleQuery()
}

// 分页大小变化
const handleSizeChange = (size) => {
  queryParams.pageSize = size
  debouncedQuery()
}

// 页码变化
const handleCurrentChange = (current) => {
  queryParams.pageNum = current
  debouncedQuery()
}

// 新增项目
const handleAdd = () => {
  dialogTitle.value = '新增项目'
  formData.value = {
    name: '',
    projectCategoryId: undefined,
    description: '',
    cover: '',
    videoUrl: '',
    fileName: '',
    password: '',
    price: 0,
    techStack: '',
    status: 1
  }
  dialogVisible.value = true
}

// 编辑项目
const handleEdit = async (row) => {
  dialogTitle.value = '编辑项目'
  const loading = ElLoading.service({
    lock: true,
    text: '正在加载项目信息...',
    background: 'rgba(0, 0, 0, 0.7)'
  })

  try {
    const res = await getProjectById(row.id)
    if (res.code === 200) {
      formData.value = { ...res.data }
      dialogVisible.value = true
    } else {
      ElMessage.error({
        message: res.msg || '获取项目详情失败',
        duration: 3000,
        showClose: true
      })
    }
  } catch (error) {
    if (!error.code || error.code !== 403) {
      ElMessage.error({
        message: '获取项目详情出错，请稍后重试',
        duration: 3000,
        showClose: true
      })
    }
  } finally {
    loading.close()
  }
}

// 删除项目
const handleDelete = (row) => {
  ElMessageBox.confirm(
    `确定要删除项目「${row.name}」吗？此操作不可逆。`,
    '删除确认',
    {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning',
    }
  ).then(() => {
    // 使用同步加载
    const loading = ElLoading.service({
      lock: true,
      text: '正在删除...',
      background: 'rgba(0, 0, 0, 0.7)'
    })
    
    // 同步删除操作
    deleteProjectById(row.id)
      .then(res => {
        if (res.code === 200) {
          ElMessage.success('删除成功')
          getList() // 刷新列表
        } else {
          ElMessage.error(res.msg || '删除失败')
        }
      })
      .catch(error => {
        if (!error.code || error.code !== 403) {
          ElMessage.error('删除失败，请稍后重试')
        }
      })
      .finally(() => {
        loading.close()
      })
  }).catch(() => {
    // 用户取消操作
  })
}

// 提交表单
const submitForm = async () => {
  if (!formRef.value) return

  await formRef.value.validate(async (valid) => {
    if (!valid) return
    
    submitLoading.value = true
    try {
      const res = await saveProject(formData.value)
      if (res.code === 200) {
        ElMessage.success(formData.value.id ? '更新成功' : '添加成功')
        dialogVisible.value = false
        getList() // 刷新列表
      } else {
        ElMessage.error(res.msg || '保存失败')
      }
    } catch (error) {
      ElMessage.error('保存失败，请稍后重试')
    } finally {
      submitLoading.value = false
    }
  })
}

// 查看视频
const handleViewVideo = (row) => {
  if (row.videoUrl) {
    window.open(row.videoUrl, '_blank')
  } else {
    ElMessage.warning('该项目没有视频')
  }
}

// 监听对话框关闭
watch(viewDialogVisible, (newVal) => {
  if (!newVal && isVideoPlaying.value) {
    isVideoPlaying.value = false;
    if (videoPlayer.value) {
      videoPlayer.value.pause();
      videoPlayer.value.currentTime = 0;
    }
  }
})

// 页面加载时初始化数据
onMounted(() => {
  getCategoryList()
  getList()
})

// 文本截断函数
const truncateText = (text, length) => {
  if (!text) return '';
  return text.length > length ? text.substring(0, length) + '...' : text;
}
</script>

<style scoped>
.projects-container {
  padding: 20px;
}

.main-card {
  background-color: #fff;
  border-radius: 4px;
  box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
  padding: 20px;
}

.card-header {
  margin-bottom: 20px;
  border-bottom: 1px solid #f0f0f0;
  padding-bottom: 10px;
}

.card-title {
  font-size: 18px;
  color: #333;
  margin: 0;
  font-weight: 500;
}

.search-section {
  margin-bottom: 20px;
  padding: 16px;
  background-color: #f8f8f8;
  border-radius: 4px;
}

.search-container {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  align-items: flex-end;
}

.search-item {
  display: flex;
  flex-direction: column;
  min-width: 200px;
}

.search-label {
  margin-bottom: 8px;
  font-size: 14px;
  color: #606266;
}

.search-input {
  width: 100%;
}

.search-buttons {
  display: flex;
  gap: 10px;
  margin-left: auto;
  align-self: flex-end;
}

.table-toolbar {
  margin-bottom: 16px;
  display: flex;
  justify-content: flex-start;
}

.pagination-container {
  margin-top: 20px;
  display: flex;
  justify-content: flex-end;
}

.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}

.action-button {
  margin-right: 8px;
}

.tag-item {
  margin-right: 4px;
  margin-bottom: 4px;
}

.tech-stack-tags {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 4px;
}

.form-select {
  width: 100%;
}

.form-tip {
  font-size: 12px;
  color: #909399;
  margin-top: 4px;
}

.image-placeholder {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 60px;
  height: 60px;
  background-color: #f5f7fa;
  color: #909399;
  border-radius: 4px;
}

.upload-container {
  width: 100%;
}

.preview-container {
  display: flex;
  align-items: center;
  margin-bottom: 8px;
  position: relative;
  width: 100%;
  border: 1px dashed #dcdfe6;
  border-radius: 4px;
  padding: 10px;
}

.preview-actions {
  position: absolute;
  top: 0;
  right: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5);
  color: #fff;
  opacity: 0;
  transition: opacity 0.3s;
}

.preview-container:hover .preview-actions {
  opacity: 1;
}

.upload-area {
  display: flex;
  width: 100%;
}

.upload-tip {
  margin-top: 8px;
  font-size: 12px;
  color: #909399;
}

.price-input-container {
  display: flex;
  align-items: center;
  gap: 10px;
}

.price-input {
  flex: 1;
}

.video-preview, .file-preview {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 10px;
}

.video-preview .el-icon, .file-preview .el-icon {
  font-size: 24px;
}

/* 项目资源样式 */
.project-resources {
  padding: 16px;
}

.resources-list {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.resource-card {
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
  overflow: hidden;
  background-color: #fff;
  border: 1px solid #ebeef5;
}

.resource-card-header {
  padding: 12px 20px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  background-color: #f8f9fa;
  border-bottom: 1px solid #ebeef5;
}

.resource-title {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 500;
  font-size: 16px;
  color: #303133;
}

.resource-title .el-icon {
  color: #409eff;
}

.resource-card-body {
  padding: 20px;
  display: flex;
  justify-content: center;
  min-height: 120px;
}

.cover-image {
  max-width: 100%;
  max-height: 300px;
  border-radius: 4px;
}

.image-placeholder {
  width: 100%;
  height: 200px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background-color: #f5f7fa;
  color: #909399;
  gap: 8px;
}

.image-placeholder .el-icon {
  font-size: 32px;
}

.video-thumbnail {
  width: 100%;
  height: 200px;
  background-color: #000;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.3s;
  gap: 8px;
}

.video-thumbnail:hover {
  background-color: #222;
}

.video-thumbnail span {
  color: #fff;
  margin-top: 8px;
}

.play-icon {
  font-size: 48px;
  color: #fff;
}

.video-player-container {
  width: 100%;
}

.video-player {
  width: 100%;
  max-height: 400px;
  border-radius: 4px;
}

.file-body {
  align-items: flex-start;
}

.file-info {
  display: flex;
  align-items: center;
  gap: 16px;
  width: 100%;
}

.file-icon {
  font-size: 48px;
  color: #409eff;
  display: flex;
  align-items: center;
  justify-content: center;
}

.file-details {
  flex: 1;
}

.file-name {
  font-weight: 500;
  color: #303133;
  margin-bottom: 4px;
  word-break: break-all;
}

.file-type {
  color: #909399;
  font-size: 14px;
}

.description-cell {
  max-width: 100%;
  display: flex;
  justify-content: center;
}

.description-tag {
  max-width: 100%;
  cursor: pointer;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 13px;
  padding: 5px 12px;
}

.description-popover {
  max-height: 300px;
  overflow-y: auto;
}

.description-title {
  font-weight: bold;
  margin-bottom: 10px;
  padding-bottom: 8px;
  border-bottom: 1px solid #eee;
  color: #303133;
}

.description-content {
  color: #606266;
  line-height: 1.5;
  word-break: break-word;
  white-space: pre-wrap;
}

.no-description {
  color: #909399;
  font-size: 13px;
  font-style: italic;
}

.no-resources {
  padding: 40px 0;
}

/* 移除进度条相关样式 */
</style>